package com.agent.vpsserver.common.utils.sign;


import com.agent.vpsserver.common.utils.common.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * description
 *
 * @author <a href="mailto:ludezh@dingtalk.com"> ludezh </a>
 * @version 1.0.0   2018/11/16,10:14
 * @since 1.0.0     2018/11/16,10:14
 */
@Slf4j
public class SignUtils {
    /**
     * 签名验证
     *
     * @param paramMap
     * @param privateKey
     * @return
     */
    public static boolean isAccessValidSign(Map<String, Object> paramMap, String privateKey) {
        String sign = paramMap.get("sign").toString();
        String strOri = signAccessOriginal(paramMap, privateKey);
        String result = Md5Utils.getMd5(strOri);
        log.info("客户端加密串sign:\n" + sign);
        log.info("服务器端md5加密前:\n" + strOri);
        log.info("服务器端md5加密后:\n" + result);
        return result.equals(sign);
    }

    /**
     * 签名验证
     *
     * @param paramMap
     * @param token
     * @return
     */
    public static boolean isValidSign(Map<String, Object> paramMap, String token) {
        String sign = paramMap.get("sign").toString();
        String result = SignUtils.getSignStr(paramMap, token);
        return result.equals(sign);
    }

    /**
     * 签名
     *
     * @param paramMap
     * @param token
     * @return
     */
    public static String getSignStr(Map<String, Object> paramMap, String token) {
        String strOri = signOriginal(paramMap, token);
        String result = Md5Utils.getMd5(strOri);
        result = result + "&key=";
        if (StringUtils.isNotBlank(token)) {
            result += token;
        }
        return Md5Utils.getMd5(result);
    }

    /**
     * 拼接加密串(K按字典降序拼接) V为数组或者集合不拼接(前后端对此数据类型处理不统一) 前后均拼接私钥
     *
     * @param paramMap
     * @param privateKey
     * @return
     */
    public static String signAccessOriginal(Map<String, Object> paramMap, String privateKey) {
        paramMap.remove("sign");
        Iterator<String> keys = paramMap.keySet().iterator();
        List<String> nameList = new ArrayList<>();
        String key = null;
        while (keys.hasNext()) {
            key = keys.next();
            if (!TextUtils.isEmpty(paramMap.get(key).toString())) {
                nameList.add(key);
            }
        }
        //参数排序
        nameList.sort(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2) {
                if (str1.compareTo(str2) > 0) {
                    return -1;
                } else if (str1.compareTo(str2) < 0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        StringBuilder stringBuffer = new StringBuilder();
        String name = null;
        Object obj = null;
        stringBuffer.append("key=").append(privateKey);
        for (int i = 0; i < nameList.size(); i++) {
            stringBuffer.append("&");
            name = nameList.get(i);
            stringBuffer.append(name);
            stringBuffer.append("=");
            obj = paramMap.get(name);
            if (!(obj instanceof Iterable) && !(obj instanceof Arrays)) {
                stringBuffer.append(obj.toString());
            }
        }
        if (!TextUtils.isEmpty(privateKey)) {
            stringBuffer.append("&key=");
            stringBuffer.append(privateKey);
        }
        return stringBuffer.toString();
    }

    /**
     * 拼接加密串(K按字典升序拼接) V为数组或者集合不拼接(前后端对此数据类型处理不统一) 字符串后需拼接私钥
     *
     * @param paramMap
     * @param accountSecKey
     * @return
     */
    public static String signOriginal(Map<String, Object> paramMap, String accountSecKey) {
        paramMap.remove("sign");
        String paramStr = SignUtils.sort(paramMap);
        StringBuilder stringBuffer = new StringBuilder(paramStr);
        stringBuffer.append("&");
        stringBuffer.append("key");
        stringBuffer.append("=");
        if (StringUtils.isNotBlank(accountSecKey)) {
            stringBuffer.append(accountSecKey);
        }
        return stringBuffer.toString();
    }

    /**
     * 参数排序，按key从小到大排序
     * @param paramMap 参数
     * @return 字符串
     */
    public static String sort(Map<String, Object> paramMap) {
        Iterator<String> keys = paramMap.keySet().iterator();
        List<String> nameList = new ArrayList<>();
        String key = null;
        while (keys.hasNext()) {
            key = keys.next();
            if (paramMap.get(key) != null && StringUtils.isNotBlank(paramMap.get(key).toString())) {
                nameList.add(key);
            }
        }
        //参数排序
//        Collections.sort(nameList, new Comparator<String>() {
        nameList.sort(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2) {
                if (str1.compareTo(str2) < 0) {
                    return -1;
                } else if (str1.compareTo(str2) > 0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        StringBuilder stringBuffer = new StringBuilder();
        String name = null;
        Object obj = null;
        for (int i = 0; i < nameList.size(); i++) {
            if (i != 0) {
                stringBuffer.append("&");
            }
            name = nameList.get(i);
            stringBuffer.append(name);
            stringBuffer.append("=");
            obj = paramMap.get(name);
            if (!(obj instanceof Iterable) && !(obj instanceof Arrays)) {
                stringBuffer.append(obj.toString());
            }
        }
        return stringBuffer.toString();
    }
}
